/**
 * 变量
 */

// 定义变量
var message; // 定义未赋值都是undefined

console.log("message1:", message); // undefined

message = "hello"; // 重新赋值
message = 100; // 重新赋值，合法，不推荐

// var 作用域
function test() {
  var message2 = "hello"; // 局部变量
  // message3 = "hi"; // 省略var，就变成全局变量，严格模式下会报错ReferenceError，不推荐
}
test();
// console.log(message2); // ReferenceError
// console.log(message3); // ReferenceError: message3 is not defined

// var 声明提升
function foo() {
  console.log('age:', age);
  var age = 26;
}
foo(); // age为undefined


/**
 * let 声明的范围是块作用域，不同于var，var声明的范围是函数作用域
 */
if (true) {
  var foo = 'Matt';
  console.log(foo); // Matt
}
console.log(foo); // Matt

if (true) {
  let bar = 'Matt';
  console.log(bar); // Matt
}
console.log(bar); // ReferenceError: bar is not defined


var foo2;
var foo2;
// let bar2;
let bar2; // SyntaxError；标识符 age 已经声明过了



/**
 * 暂时性死区(temporaldead zone）)
 * let 与 var 的另一个重要的区别，就是 let 声明的变量不会在作用域中被提升
 */
// name 会被提升
console.log(foo3); // undefined
var foo3 = 'Matt';
// age 不会被提升
console.log(bar3); // ReferenceError： age 没有定义
let bar3 = 26;

// let 在全局作用域中声明的变量不会成为 window 对象的属性，var会
// for 循环中的 let 声明，for 循环定义的迭代var变量会渗透到循环体外部。



/**
 * const
 * const 的行为与 let 基本相同，唯一一个重要的区别是用它声明变量时必须同时初始化变量，且尝试修改 const 声明的变量会导致运行时错误
 */
const foo4 = 26;
foo4 = 36; // TypeError: 给常量赋值



/**
 * 声明风格及最佳实践
 * 1. 不使用 var
 * 2. const 优先， let 次之
 */
